package org.rambadger.command;

import com.yammer.dropwizard.Service;
import com.yammer.dropwizard.cli.EnvironmentCommand;
import com.yammer.dropwizard.config.Environment;
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
import net.sourceforge.argparse4j.inf.Subparsers;
import org.mindrot.jbcrypt.BCrypt;
import org.mongojack.DBCursor;
import org.mongojack.DBQuery;
import org.mongojack.JacksonDBCollection;
import org.rambadger.command.auth.AuthUser;
import org.rambadger.command.axon.AxonBundle;
import org.rambadger.command.axon.MongoBundle;
import org.rambadger.command.command.ChangeSystemRole;
import org.rambadger.command.command.CreateAdminUser;
import org.rambadger.command.command.RegisterNewUser;


public class ConfigureAdminsCommand extends EnvironmentCommand<CommandConfiguration> {
    private final MongoBundle mongo;
    private final AxonBundle axon;
    public ConfigureAdminsCommand(Service service, MongoBundle mongo, AxonBundle axon) {
        super(service, "admins", "Configure the system administrators.");
        this.mongo = mongo;
        this.axon = axon;
    }

    @Override
    public void configure(Subparser subparser) {
        super.configure(subparser);
        Subparsers subparsers = subparser.addSubparsers().dest("action").help("action to perform");

        Subparser newAdmin = subparsers.addParser("create").help("Create a new user, and grant them application wide admin rights.");
        newAdmin.addArgument("username").type(String.class);
        newAdmin.addArgument("password").type(String.class);
        newAdmin.addArgument("email").type(String.class);

        Subparser listAdmins = subparsers.addParser("list").help("List all users with system wide admin access.");

        Subparser grantAdmin = subparsers.addParser("grant").help("Grant admin rights to an existing user.");
        grantAdmin.addArgument("username").type(String.class);

        Subparser revokeAdmin = subparsers.addParser("revoke").help("Revoke admin rights from an existing user.");
        revokeAdmin.addArgument("username").type(String.class);
    }

    @Override
    protected void run(Environment environment, Namespace namespace, CommandConfiguration configuration) throws Exception {
        String action = namespace.getString("action");
        switch (action) {
            case "grant":
                axon.getCommandGateway().send(new ChangeSystemRole.GrantAdmin(namespace.getString("username")));
                break;
            case "revoke":
                axon.getCommandGateway().send(new ChangeSystemRole.RevokeAdmin(namespace.getString("username")));
                break;
            case "create":
                String username = namespace.getString("username");
                String pwHash = BCrypt.hashpw(namespace.getString("password"), BCrypt.gensalt());
                String email = namespace.getString("email");
                String firstName = namespace.getString("firstName");
                String lastName = namespace.getString("lastName");
                //TODO: Make a single command
                axon.getCommandGateway().send(new CreateAdminUser(username, pwHash, email, firstName, lastName));
                break;
            case "list":
                listAdmins();
                break;
        }
    }

    private void listAdmins() {
        JacksonDBCollection<AuthUser, String> users = mongo.getWrappedCollection(AuthUser.class);
        DBCursor<AuthUser> found = users.find(DBQuery.is("hasSystemAdmin", true));
        System.out.println("Admins:");
        for (AuthUser user : found) System.out.println(user.getUsername());
    }
}
